package com.yenlien.traceyun.common.crypt;

import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.common.bean.UserInfo;
import com.yenlien.traceyun.common.exception.TokenException;

/**
 * @author: bigwangy@sina.com
 * @create: 2020-03-09
 * @description: 根据jwt的原则生成token
 **/
public class TokenUtil {

    //token最大有效期（分钟）
    private static int MAX_TOKEN_TIME = 15;

    //刷新token最大有效期（分钟）
    private static int MAX_REFRESH_TOKEN_TIME = 1440;


    /**
     * 生成token
     *
     * @param body   签名主体
     * @param secret 加密秘钥
     * @param expire 过期时间分钟数
     * @return
     */
    public static String getToken(String body, String secret, int expire) {
        if (expire == 0) {
            expire = MAX_TOKEN_TIME;
        }
        JSONObject header = new JSONObject();
        header.put("alg", "HS256");
        long currentime = System.currentTimeMillis();
        header.put("createtime", currentime);
        long ex = currentime + expire * 60L * 1000L;
        header.put("expire", ex);
        String baseheader = (CryptUtil.base64Encode(header.toJSONString()));
        String basebody = (CryptUtil.base64Encode(body));
        String sign = (CryptUtil.sha256(baseheader + "." + basebody + secret));
        return baseheader + "." + basebody + "." + sign;
    }

    /**
     * 生成刷新token
     *
     * @param secret
     * @param expire
     * @return
     */
    public static String getRefreshToken(String secret, int expire) {
        if (expire == 0) {
            expire = MAX_REFRESH_TOKEN_TIME;
        }
        long refreshTokenExpire = System.currentTimeMillis() + expire * 60 * 1000;
        String baseRefresh = (CryptUtil.base64Encode(refreshTokenExpire + ""));
        String sign = CryptUtil.sha256(baseRefresh + secret);
        return baseRefresh + "." + sign;
    }


    /**
     * 验证token是否有效
     *
     * @param token
     * @param secert
     * @return
     */
    public static boolean veryToken(String token, String secert) throws TokenException {

        String[] arrs = token.split("\\.");
        if (arrs.length != 3) {//格式不正确
            throw new TokenException("token格式不正确");
        }
        String sign = CryptUtil.sha256(arrs[0] + "." + arrs[1] + secert);
        if (!sign.equals(arrs[2])) {
            throw new TokenException("token验证错误");
        }
        String header = CryptUtil.base64Decode(arrs[0]);
        try {
            JSONObject headerObj = JSONObject.parseObject(header);
            long expire = headerObj.getLong("expire");

            if (expire < System.currentTimeMillis()) {
                throw new TokenException("token过期");
            }
        } catch (Exception e) {
            if (e instanceof TokenException) {
                throw e;
            }
            throw new TokenException("token格式不正确");
        }
        return true;
    }

    /**
     * 检验刷新token
     *
     * @param refresh
     * @param secert
     * @return
     */
    public static boolean veryRefresh(String refresh, String secert) throws TokenException {
        String[] arrs = refresh.split("\\.");
        if (arrs.length != 2) {//格式不正确
            throw new TokenException("refresh格式不正确");
        }
        String sign = CryptUtil.sha256(arrs[0] + secert);
        if (!sign.equals(arrs[1])) {
            throw new TokenException("refresh验证错误");
        }
        long refreshtime = Long.valueOf(CryptUtil.base64Decode(arrs[0]));
        if (refreshtime < System.currentTimeMillis()) {
            throw new TokenException("refresh过期");
        }
        return true;
    }

    /**
     * 获取token中的body
     *
     * @param token
     * @return
     */
    public static String getBody(String token) {
        String body = token.split("\\.")[1];
        return CryptUtil.base64Decode(body);
    }

    /**
     * 获取token中的body
     *
     * @param token
     * @return
     */
    public static UserInfo getUserInfo(String token) {
        String body = token.split("\\.")[1];
        JSONObject json = JSONObject.parseObject(CryptUtil.base64Decode(body));
        return json.toJavaObject(UserInfo.class);
    }

    public static void main(String[] args) {
        String token = "eyJjcmVhdGV0aW1lIjoxNjE1Mjc0ODQ1MDkzLCJleHBpcmUiOjE2MTgyNzQ4NDUwOTMsImFsZyI6IkhTMjU2In0=.eyJpZCI6IjEiLCJwYWdlIjowLCJjb21wYW55SWQiOiIxIiwibmFtZSI6IjAwMSIsInVzZXJuYW1lIjoiMDAxIiwicGFzc3dvcmQiOiI0Mjk3ZjQ0YjEzOTU1MjM1MjQ1YjI0OTczOTlkN2E5MyIsInBob25lIjoiMTIyMjIiLCJ1c2VyVHlwZSI6IkFETUlOIiwibG9ja2VkIjpmYWxzZX0=.ecd1557840a51b3893ecc940694357b7e5f9b3f70033ad7daacdfe8cf12f1859";
        boolean r = veryToken(token, "123456");
        System.out.println(r);

    }
}
